Implement ostree::checksum_file_async
authorFelix Krull <f_krull@gmx.de>
Mon, 2 Sep 2019 11:27:54 +0000 (13:27 +0200)
committerColin Walters <walters@verbum.org>
Fri, 6 May 2022 16:53:54 +0000 (12:53 -0400)
These might not work, I didn't test them...

rust-bindings/rust/src/functions.rs

index a56e0da2e6c36fc6549916afcb0752eb9fe176fd..a017e049779ea2c55e4d6301fed11be7bbdbcbb1 100644 (file)
@@ -1,8 +1,13 @@
 use crate::{Checksum, ObjectType};
+#[cfg(feature = "futures")]
+use futures::future;
 use glib::prelude::*;
 use glib::translate::*;
 use glib_sys::GFALSE;
+#[cfg(feature = "futures")]
+use std::boxed::Box as Box_;
 use std::error::Error;
+use std::mem::MaybeUninit;
 use std::ptr;
 
 pub fn checksum_file<P: IsA<gio::File>, Q: IsA<gio::Cancellable>>(
@@ -20,19 +25,75 @@ pub fn checksum_file<P: IsA<gio::File>, Q: IsA<gio::Cancellable>>(
             cancellable.map(|p| p.as_ref()).to_glib_none().0,
             &mut error,
         );
+        checksum_file_error(out_csum, error, ret)
+    }
+}
 
-        if !error.is_null() {
-            Err(Box::<glib::Error>::new(from_glib_full(error)))
-        } else if ret == GFALSE {
-            Err(Box::new(glib_bool_error!(
-                "unknown error in ostree_checksum_file"
-            )))
-        } else {
-            Ok(Checksum::from_glib_full(out_csum))
-        }
+pub fn checksum_file_async<
+    P: IsA<gio::File>,
+    Q: IsA<gio::Cancellable>,
+    R: FnOnce(Result<Checksum, Box<dyn Error>>) + Send + 'static,
+>(
+    f: &P,
+    objtype: ObjectType,
+    io_priority: i32,
+    cancellable: Option<&Q>,
+    callback: R,
+) {
+    let user_data: Box<R> = Box::new(callback);
+    unsafe extern "C" fn checksum_file_async_trampoline<
+        R: FnOnce(Result<Checksum, Box<dyn Error>>) + Send + 'static,
+    >(
+        _source_object: *mut gobject_sys::GObject,
+        res: *mut gio_sys::GAsyncResult,
+        user_data: glib_sys::gpointer,
+    ) {
+        let mut error = ptr::null_mut();
+        let mut out_csum = MaybeUninit::uninit();
+        let ret = ostree_sys::ostree_checksum_file_async_finish(
+            _source_object as *mut _,
+            res,
+            out_csum.as_mut_ptr(),
+            &mut error,
+        );
+        let out_csum = out_csum.assume_init();
+        let result = checksum_file_error(out_csum, error, ret);
+        let callback: Box<R> = Box::from_raw(user_data as *mut _);
+        callback(result);
+    }
+    let callback = checksum_file_async_trampoline::<R>;
+    unsafe {
+        ostree_sys::ostree_checksum_file_async(
+            f.as_ref().to_glib_none().0,
+            objtype.to_glib(),
+            io_priority,
+            cancellable.map(|p| p.as_ref()).to_glib_none().0,
+            Some(callback),
+            Box::into_raw(user_data) as *mut _,
+        );
     }
 }
 
+#[cfg(feature = "futures")]
+pub fn checksum_file_async_future<P: IsA<gio::File> + Clone + 'static>(
+    f: &P,
+    objtype: ObjectType,
+    io_priority: i32,
+) -> Box_<dyn future::Future<Output = Result<Checksum, Box<dyn Error>>> + std::marker::Unpin> {
+    use fragile::Fragile;
+    use gio::GioFuture;
+
+    let f = f.clone();
+    GioFuture::new(&f, move |f, send| {
+        let cancellable = gio::Cancellable::new();
+        let send = Fragile::new(send);
+        checksum_file_async(f, objtype, io_priority, Some(&cancellable), move |res| {
+            let _ = send.into_inner().send(res);
+        });
+        cancellable
+    })
+}
+
 pub fn checksum_file_from_input<P: IsA<gio::InputStream>, Q: IsA<gio::Cancellable>>(
     file_info: &gio::FileInfo,
     xattrs: Option<&glib::Variant>,
@@ -52,15 +113,20 @@ pub fn checksum_file_from_input<P: IsA<gio::InputStream>, Q: IsA<gio::Cancellabl
             cancellable.map(|p| p.as_ref()).to_glib_none().0,
             &mut error,
         );
+        checksum_file_error(out_csum, error, ret)
+    }
+}
 
-        if !error.is_null() {
-            Err(Box::<glib::Error>::new(from_glib_full(error)))
-        } else if ret == GFALSE {
-            Err(Box::new(glib_bool_error!(
-                "unknown error in ostree_checksum_file_from_input"
-            )))
-        } else {
-            Ok(Checksum::from_glib_full(out_csum))
-        }
+unsafe fn checksum_file_error(
+    out_csum: *mut [*mut u8; 32],
+    error: *mut glib_sys::GError,
+    ret: i32,
+) -> Result<Checksum, Box<dyn Error>> {
+    if !error.is_null() {
+        Err(Box::<glib::Error>::new(from_glib_full(error)))
+    } else if ret == GFALSE {
+        Err(Box::new(glib_bool_error!("unknown error")))
+    } else {
+        Ok(Checksum::from_glib_full(out_csum))
     }
 }